package com.sakhalin.news.ui.news

import android.annotation.SuppressLint
import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.Card
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Text
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
import com.sakhalin.news.models.ItemType
import com.sakhalin.news.models.news.NewsItem
import com.sakhalin.news.ui.other.ErrorItem
import com.sakhalin.news.ui.other.ErrorView
import com.sakhalin.news.ui.other.LoadingItem
import com.sakhalin.news.ui.theme.Blue
import com.sakhalin.news.viewmodels.NewsListViewModel
import java.text.SimpleDateFormat
import java.util.*

@SuppressLint("SimpleDateFormat")
private val readableFormat = SimpleDateFormat("EEEE, d MMMM ")
private val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)


@OptIn(ExperimentalMaterialApi::class)
@Composable
fun NewsListView(
    category: String,
    viewModel: NewsListViewModel = viewModel(factory = NewsListViewModel.Factory(newsCategory = category), key = category),
    navController: NavHostController
) {
    val newsList = viewModel.newsList.collectAsLazyPagingItems()
    val lazyListState: LazyListState = rememberLazyListState()

    val context = LocalContext.current

    val state = rememberPullRefreshState(newsList.loadState.refresh is LoadState.Loading,
        {
            newsList.refresh()
        }
    )

    Box(Modifier.pullRefresh(state)) {
        LazyColumn(
            state = lazyListState,
            modifier = Modifier
                .fillMaxSize()
                .padding(horizontal = 8.dp, vertical = 8.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {

            val newsItems = newsList.itemSnapshotList.items

            itemsIndexed(items = newsItems, itemContent = { index, item ->

                    when (item.type) {
                        ItemType.Item -> {
                            //Если это первый элемент списка, то показыаем дату сверху
                            if (index == 0) {
                                //Добавляем дату к новости и проверяем разницу в днях
                                //пишем соотв. надпись
                                DateItemView(
                                    text = when (getDaysDifference(dateFormat.parse(item.date), Date())) {
                                        0 -> "Сегодня"
                                        1 -> "Вчера"
                                        else -> readableFormat.format(dateFormat.parse(item.date))
                                    }
                                )
                            } else {
                                //Если это не первый элемент, то сравниваем количество дней между датой новостей(текущая с предыдущей)
                                newsList[index - 1]?.let { previousNews ->
                                    //Если разница между текущей и предыдущей есть, то добавляем виджет с датой
                                    if (getDaysDifference(dateFormat.parse(item.date), dateFormat.parse(previousNews.date)) > 0) {
                                        //Добавляем виджет с датой и проверяем разницу в сегоднящней и датой новости
                                        //и пишем соотв. надпись
                                        DateItemView(
                                            text = when (getDaysDifference(dateFormat.parse(item.date), Date())) {
                                                1 -> "Вчера"
                                                else -> readableFormat.format(dateFormat.parse(item.date))
                                            }
                                        )
                                    }
                                }
                            }

                            //Добавляем ячейку новости
                              NewsItemView(newsItem = item, modifier = Modifier
                                  .fillMaxWidth()
                                  .clickable {
                                      navController.navigate("news/${item.id}") {
                                          // Pop up to the start destination of the graph to
                                          // avoid building up a
                                          // large stack of destinations
                                          // on the back stack as users select items
                                          navController.graph.startDestinationRoute?.let { route ->
                                              popUpTo(route) {
                                                  saveState = true
                                              }
                                          }
                                          // Avoid multiple copies of the same destination when
                                          // reselecting the same item
                                          launchSingleTop = true
                                          // Restore state when reselecting a previously selected item
                                          //restoreState = true
                                      }
                                  })
                        }
                        ItemType.Advert -> {
                            Card(elevation = 1.dp, modifier = Modifier.fillMaxWidth()) {
                                Text(text = "Тут будет реклама!", Modifier.padding(40.dp))
                            }

                            if(isItemFullyVisible(lazyListState,index)){
                                Log.i("ADV", "Реклама на экране!")
                            }
                        }
                    }
            })

            newsList.apply {
                when {
                    loadState.append is LoadState.Loading -> {
                        Toast.makeText(context, "Загрузка...", Toast.LENGTH_SHORT).show()
                        item {
                            LoadingItem()
                        }
                    }
                    loadState.append is LoadState.Error -> {
                        val error = newsList.loadState.append as LoadState.Error
                        item {
                            ErrorItem(message = error.error.message!!, onClickRetry = {
                                retry()
                            })
                        }
                    }
                    loadState.refresh is LoadState.Error -> {
                        val error = newsList.loadState.refresh as LoadState.Error
                        item {
                            ErrorView(
                                errorText = error.error.message!!,
                                modifier = Modifier.fillParentMaxSize(),
                                onClickRetry = { retry() }
                            )
                        }
                    }
                }
            }
        }

        PullRefreshIndicator(
            newsList.loadState.refresh is LoadState.Loading,
            state,
            Modifier.align(Alignment.TopCenter),
            contentColor = Blue
        )
    }
}


private fun isItemFullyVisible(lazyListState: LazyListState, editTagItemIndex: Int): Boolean {
    with(lazyListState.layoutInfo) {
        val editingTagItemVisibleInfo = visibleItemsInfo.find { it.index == editTagItemIndex }
        return if (editingTagItemVisibleInfo == null) {
            false
        } else {
            viewportEndOffset - editingTagItemVisibleInfo.offset >= editingTagItemVisibleInfo.size
        }
    }
}


@Composable
fun DateItemView(text: String) {
    Text(
        text = text, color = Color.Gray, fontSize = 18.sp, modifier = Modifier
            .fillMaxWidth()
            .wrapContentSize(align = Alignment.Center)
            .padding(10.dp)
    )
}


private fun getDaysDifference(fromDate: Date, toDate: Date): Int {
    return ((toDate.time - fromDate.time) / (1000 * 60 * 60 * 24)).toInt()
}